/*
 * @Author: 肖思汗
 * @Date: 2020-02-12 16:57:12
 * @Last Modified by: 肖思汗
 * @Last Modified time: 2020-04-13 23:19:14
 */

import * as THREE from 'three';

import transition from './transition.js';

import Color from './Color.js';

import { Line2 } from 'three/examples/jsm/lines/Line2';

import creatPoints from './creatPoints.js';

const isFunction = obj => obj instanceof Function;

let Shape = new THREE.Shape();
Shape.moveTo(0, 0);
Shape.absarc(0, 0, 1, 0, Math.PI * 1.9, false);
Shape.lineTo(0, 0);

const SectorBufferGeometry = new THREE.ExtrudeBufferGeometry(Shape, {
    depth: 0.1,
    steps: 1,
    bevelEnabled: false,
    bevelThickness: 100,
    bevelSize: 0,
    bevelSegments: 0,
    curveSegments: 100
}); // 扇形立体网格模型

const LambertMaterial = new THREE.MeshLambertMaterial({
    wireframe: false, // 调试用
    transparent: true // 开启透明
});// 兰伯特材质

// 创建一个扇形
export default function pieMesh(startAngle, color, labelGap, globalIndex) {

    // 饼模型
    let pieMesh = new class pieMesh extends THREE.Mesh { }(SectorBufferGeometry.clone(), LambertMaterial.clone());

    pieMesh.totooltipDOM = null;// 提示框的dom

    pieMesh.line = new Line2();

    pieMesh.line.geometry.setPositions([0, 0, 0, 0, 0, 0, 0, 0, 0]);

    pieMesh.line.material.linewidth = 0.005; // 线宽

    pieMesh.line.material.transparent = true;

    pieMesh.line.computeLineDistances(); // 虚线计算

    pieMesh.add(pieMesh.line);

    pieMesh.text = creatPoints();

    pieMesh.add(pieMesh.text);

    pieMesh.color = new Color(color); // 颜色缓动

    pieMesh.labelGap = labelGap; // 防止标签重叠，设置大于0的值时，可以在z轴呈现等差高度

    pieMesh.renderOrder = 0; // 默认渲染顺序为0 不透明时 设置为1

    pieMesh.parame = new transition({ // 创建3个缓动参数
        startAngle: startAngle,
        endAngle: startAngle,
        height: 0
    });

    pieMesh.cursor = 'pointer';

    // pieMesh.onClick = e => {
    //     console.log(e);
    // };

    pieMesh.onMouseenter = e => {
        pieMesh.parent.children.map(mesh => {
            mesh.material.opacity = 0.5; // 所有饼的透明度都设为 0.5
            mesh.renderOrder = 1;//

            mesh.line.material.uniforms.opacity.value = 0.5; // 所有线的透明度都设为 0.5
            mesh.line.renderOrder = 1;

            // mesh.text.material.opacity = 0.5; // 所有文字的透明度都设为 0.5
            // mesh.text.renderOrder = 1;

            mesh.parame.height = mesh.userData.height || 0.1;

        });

        pieMesh.material.opacity = 1; // 自己的透明度1
        pieMesh.renderOrder = 0;

        pieMesh.line.material.uniforms.opacity.value = 1;  // 自己的透明度1
        pieMesh.line.renderOrder = 0;

        // pieMesh.text.material.opacity = 1; // 自己的透明度都设为 0.5
        // pieMesh.text.renderOrder = 0;

        pieMesh.totooltipDOM.style.opacity = 1;

        pieMesh.totooltipDOM.style.opacity = 1;

        pieMesh.parame.height = pieMesh.userData.cursorHeight || pieMesh.userData.height || 0.1;

        if (isFunction(pieMesh.setTotooltip)) {
            pieMesh.totooltipDOM.innerHTML = pieMesh.setTotooltip(pieMesh.userData);
        }

    };

    pieMesh.onMouseleave = e => {
        pieMesh.parent.children.map(mesh => {
            mesh.material.opacity = 1; // 所有饼的透明度 恢复到1
            mesh.renderOrder = 0;

            mesh.line.material.uniforms.opacity.value = 1; // 所有线的透明度 恢复到1
            mesh.line.renderOrder = 0;

            // mesh.text.material.opacity = 1; // 自己的透明度都设为 0.5
            // mesh.text.renderOrder = 0;

            mesh.parame.height = mesh.userData.height || 0.1;
        });

        pieMesh.totooltipDOM.style.opacity = 0;
    };

    pieMesh.onBeforeRender = (() => {

        let i = 0; // 计数器
        let height = 0; // 高度计算
        let startAngle = 0; // 起始角度
        let endAngle = 0; // 起始角度
        let Vec = new THREE.Vector2(1, 0);    // 二维向量 rotateAround
        let center = new THREE.Vector2(0, 0); // 旋转中心
        let angle = 0; // 向量当前的角度

        let PieGeomartryPosition = null; // 顶点数组

        let Zaxis = new THREE.Vector3(0, 0, 1);// z轴向量

        let linePoint2 = new THREE.Vector3; // 用于计算线的第二个点的位置

        return function(renderer, scene, camera, geometry, material) {

            if (this.parame.timeProgress < 0.5) {
                this.isAnimention = true;
            }

            if (this.isAnimention === false) {
                return;
            }

            height = this.parame.height;
            startAngle = this.parame.startAngle;
            endAngle = this.parame.endAngle;

            PieGeomartryPosition = SectorBufferGeometry.attributes.position.array; // 顶点数组

            for (i = 0; i < geometry.attributes.position.array.length; i += 3) {

                // 修改顶点坐标
                Vec.set(
                    PieGeomartryPosition[i],
                    PieGeomartryPosition[i + 1],
                );

                angle = Vec.angle(); // 当前向量的角度

                // 旋转到合适的角度
                Vec.rotateAround(center,
                    ((angle / Math.PI / 1.9) * (endAngle - startAngle)) + startAngle - angle
                );

                geometry.attributes.position.array[i] = Vec.x;
                geometry.attributes.position.array[i + 1] = Vec.y;

                if (PieGeomartryPosition[i + 2] > 0) {
                    geometry.attributes.position.array[i + 2] = height;
                }

                geometry.attributes.position.needsUpdate = true;

            }

            geometry.computeVertexNormals(); // 计算顶点法线

            geometry.computeBoundingSphere(); // 计算模型尺寸范围

            material.color.copy(this.color); // 饼的颜色

            pieMesh.line.material.color.copy(this.color);// 线的颜色

            pieMesh.line.position.set(1, 0, height);// 计算线的位置

            angle = (endAngle + startAngle) / 2;// 当前饼的起始角度和终止角度的中间值
            let lineSegment1 =  this.userData.lineSegment1 || 1;
            let lineSegment2 = this.userData.lineSegment2 || 1;

            let length = Math.abs(Math.sin(angle)) * lineSegment1; // 第一段线的长度

            pieMesh.line.position.applyAxisAngle(Zaxis, angle); // 计算线的位置

            // 计算线第二个点的位置
            linePoint2.set(length, 0, globalIndex * this.labelGap).applyAxisAngle(Zaxis, angle);

            pieMesh.line.geometry.attributes.instanceStart.data.array[3] = linePoint2.x;
            pieMesh.line.geometry.attributes.instanceStart.data.array[4] = linePoint2.y;
            pieMesh.line.geometry.attributes.instanceStart.data.array[5] = linePoint2.z;

            pieMesh.line.geometry.attributes.instanceStart.data.array[6] = linePoint2.x;
            pieMesh.line.geometry.attributes.instanceStart.data.array[7] = linePoint2.y;
            pieMesh.line.geometry.attributes.instanceStart.data.array[8] = linePoint2.z;

            pieMesh.line.geometry.attributes.instanceStart.data.array[9] = linePoint2.x + ((angle < Math.PI / 2 || angle > Math.PI / 2 * 3) ? lineSegment2 * 0.1 : lineSegment2 * -0.1);
            pieMesh.line.geometry.attributes.instanceStart.data.array[10] = linePoint2.y;
            pieMesh.line.geometry.attributes.instanceStart.data.array[11] = linePoint2.z;

            pieMesh.line.geometry.attributes.instanceStart.data.needsUpdate = true;
            // 计算 文字的位置
            pieMesh.text.position.x = linePoint2.x + ((angle < Math.PI / 2 || angle > Math.PI / 2 * 3) ? lineSegment2 * 0.1 + 0.1 : lineSegment2 * -0.1 - 0.1);
            pieMesh.text.position.y = linePoint2.y;
            pieMesh.text.position.z = linePoint2.z;

            pieMesh.text.textAlign = ((angle < Math.PI / 2 || angle > Math.PI / 2 * 3) ? 'left' : 'right');

            pieMesh.text.position.add(pieMesh.line.position);

            // pieMesh.text.textColor = `#${pieMesh.material.color.getHexString()}`;

            if (this.parame.timeProgress === 1) {
                this.isAnimention = false;
            }

        };

    })();

    pieMesh.onBeforeRender(null, null, null, pieMesh.geometry, pieMesh.material);

    return pieMesh;

}